package com.dsaa.code2_tree;

import java.util.*;

public class TreeNode {
    Integer val;
    TreeNode left;
    TreeNode right;

    TreeNode() {
    }

    TreeNode(Integer val) {
        this.val = val;
    }

    TreeNode(Integer val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }

    public Integer getVal() {
        return val;
    }

    public void setVal(Integer val) {
        this.val = val;
    }

    public TreeNode getLeft() {
        return left;
    }

    public void setLeft(TreeNode left) {
        this.left = left;
    }

    public TreeNode getRight() {
        return right;
    }

    public void setRight(TreeNode right) {
        this.right = right;
    }

    public static TreeNode createNode(Integer num) {
        return new TreeNode(num);
    }

    // Encodes a tree to a single string.
    public static String serialize(TreeNode root) {
        return reserialize(root, "");
    }

    // Decodes your encoded data to tree.
    public static TreeNode deserialize(String data) {
        String[] dataArray = data.split(",");
        List<String> dataList = new LinkedList<>(Arrays.asList(dataArray));
        return rdeserialize(dataList);
    }

    private static String reserialize(TreeNode root, String str) {
        if (root == null) {
            str += "null,";
        } else {
            str += String.valueOf(root.val) + ",";
            str = reserialize(root.left, str);
            str = reserialize(root.right, str);
        }
        return str;
    }

    private static TreeNode rdeserialize(List<String> dataList) {
        if (dataList.get(0).equals("null") || "".equals(dataList.get(0))) {
            dataList.remove(0);
            return null;
        }

        TreeNode root = new TreeNode(Integer.valueOf(dataList.get(0)));
        dataList.remove(0);

        root.left = rdeserialize(dataList);
        root.right = rdeserialize(dataList);

        return root;
    }

    /*
    public static TreeNode buildTree(Integer[] nums) {
        int n = nums.length;
        TreeNode root = new TreeNode(nums[0]);

        Deque<TreeNode> deque = new LinkedList<>();
        deque.add(root);
        int i = 1;
        while (deque.peekFirst() != null) {
            TreeNode node = deque.pollFirst();

            if (i < n) {
                node.left = createNode(nums[i++]);
                deque.add(node.left);
            }

            if (i < n) {
                node.right = createNode(nums[i++]);
                deque.add(node.right);
            }
        }
        return root;
    }


    public static Integer[] buildArray(TreeNode root) {
        List<Integer> ansList = new ArrayList<Integer>();
        if (root == null) {
            return null;
        }
        ansList.add(root.val);
        Deque<TreeNode> deque = new LinkedList<>();
        deque.add(root);
        while (deque.peekFirst() != null) {
            TreeNode node = deque.pollFirst();

            if (node.left != null) {
                ansList.add(node.left.val);
                deque.add(node.left);
            }

            if (node.right != null) {
                ansList.add(node.right.val);
                deque.add(node.right);
            }
        }
        return ansList.toArray(new Integer[ansList.size()]);
    }
    */
}